package co.edu.usbcali.museo.modelo.control;

import co.edu.usbcali.museo.dataaccess.daoFactory.JPADaoFactory;
import co.edu.usbcali.museo.dataaccess.entityManager.EntityManagerHelper;
import co.edu.usbcali.museo.exceptions.*;
import co.edu.usbcali.museo.modelo.Cuadro;
import co.edu.usbcali.museo.modelo.Tecnica;
import co.edu.usbcali.museo.utilities.Utilities;

import java.math.BigDecimal;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;


/**
 *
 * @author Zathura Code Generator http://code.google.com/p/zathura
 *j
 */
public class TecnicaLogic implements ITecnicaLogic {
	public List<Tecnica> getTecnica() throws Exception {
		List<Tecnica> list = new ArrayList<Tecnica>();

		try {
			list = JPADaoFactory.getInstance().getTecnicaDAO().findAll(0);
		} catch (Exception e) {
			throw new Exception(ExceptionManager.getInstance()
					.exceptionInGetAll());
		} finally {
			EntityManagerHelper.closeEntityManager();
		}

		return list;
	}

	public void saveTecnica(Long codtecnica, String nombretecnica)
	throws Exception {
		Tecnica entity = null;
		List<Tecnica> lasTenicas=null;

		try {
			String codigoTecnica = codtecnica.toString();
			String nombreTecnica= nombretecnica;

			if(codigoTecnica == null || codigoTecnica.equals("")){
				throw new Exception("El c�digo de la t�cnica es de car�cter obligatorio");
			}

			if(nombreTecnica== null || nombreTecnica.equals("")){
				throw new Exception("El nombre de la t�cnica es de car�cter obligatorio");
			}

			if(Utilities.soloNumeros(codigoTecnica)==false){
				throw new Exception("El c�digo de la t�cnica no puede contener letras ni car�cteres especiales");
			}

			if(Utilities.soloLetras(nombreTecnica)==false){
				throw new Exception("El nombre de la t�cnica no permite n�meros ni car�cteres especiales");
			}      	

			entity =  JPADaoFactory.getInstance().getTecnicaDAO().findById(codtecnica);

			if(entity!=null){
				throw new Exception("Ya existe una t�cnica con el c�digo ingresado");
			}

			lasTenicas= JPADaoFactory.getInstance().getTecnicaDAO().findByProperty("nombretecnica", nombretecnica);

			if(lasTenicas.size()!=0){
				throw new Exception("Ya existe una t�cnica con el nombre ingresado");
			}

			entity = new Tecnica();
			entity.setCodtecnica(codtecnica);
			entity.setNombretecnica(nombretecnica);
			EntityManagerHelper.beginTransaction();
			JPADaoFactory.getInstance().getTecnicaDAO().save(entity);
			EntityManagerHelper.commit();
		} catch (Exception e) {
			EntityManagerHelper.rollback();
			throw e;
		} finally {
			EntityManagerHelper.closeEntityManager();
		}
	};

	public void deleteTecnica(Long codtecnica) throws Exception {
		Tecnica entity = null;
		try {       	
			entity = JPADaoFactory.getInstance().getTecnicaDAO().findById(codtecnica);

			if(entity==null){
				throw new Exception("No se puede eliminar una t�cnica que no exista");
			}

			EntityManagerHelper.beginTransaction();
			JPADaoFactory.getInstance().getTecnicaDAO().delete(entity);
			EntityManagerHelper.commit();
		} catch (Exception e) {
			EntityManagerHelper.rollback();
			throw e;
		} finally {
			EntityManagerHelper.closeEntityManager();
		}
	}

	public void updateTecnica(Long codtecnica, String nombretecnica)
	throws Exception {
		Tecnica entity = null;
		List<Tecnica> lasTenicas=null;
		try {
			String codigoTecnica = codtecnica.toString();
			String nombreTecnica= nombretecnica;

			if(codigoTecnica== null || codigoTecnica.equals("")){
				throw new Exception("El c�digo de la t�cnica es de car�cter obligatorio");
			}

			if(nombreTecnica== null || nombreTecnica.equals("")){
				throw new Exception("El nombre de la t�cnica es de car�cter obligatorio");
			}

			if(Utilities.soloNumeros(codigoTecnica)==false){
				throw new Exception("El c�digo de la t�cnica no puede contener letras ni car�cteres especiales");
			}

			if(Utilities.soloLetras(nombreTecnica)==false){
				throw new Exception("El nombre de la t�cnica no permite n�meros ni car�cteres especiales");
			}

			entity =  JPADaoFactory.getInstance().getTecnicaDAO().findById(codtecnica);            

			if (entity == null) {
				throw new Exception("No existe la t�cnica");
			}
			
			lasTenicas= JPADaoFactory.getInstance().getTecnicaDAO().findByProperty("nombretecnica", nombretecnica);
			

			if(lasTenicas.size()!=0){
				throw new Exception("No existe el nombre");
			}

			entity.setCodtecnica(codtecnica);
			entity.setNombretecnica(nombretecnica);
			EntityManagerHelper.beginTransaction();
			JPADaoFactory.getInstance().getTecnicaDAO().update(entity);
			EntityManagerHelper.commit();
		} catch (Exception e) {
			EntityManagerHelper.rollback();
			throw e;
		} finally {
			EntityManagerHelper.closeEntityManager();
		}
	}

	public Tecnica getTecnica(Long codtecnica) throws Exception {
		Tecnica entity = null;

		try {
			entity = JPADaoFactory.getInstance().getTecnicaDAO()
			.findById(codtecnica);
		} catch (Exception e) {
			throw new Exception(ExceptionManager.getInstance()
					.exceptionFindingEntity("Tecnica"));
		} finally {
			EntityManagerHelper.closeEntityManager();
		}

		return entity;
	}

	public List<Tecnica> findPageTecnica(String sortColumnName,
			boolean sortAscending, int startRow, int maxResults)
			throws Exception {
		List<Tecnica> entity = null;

		try {
			entity = JPADaoFactory.getInstance().getTecnicaDAO()
			.findPageTecnica(sortColumnName,
					sortAscending, startRow, maxResults);
		} catch (Exception e) {
			throw new Exception(ExceptionManager.getInstance()
					.exceptionFindingEntity("Tecnica"));
		} finally {
			EntityManagerHelper.closeEntityManager();
		}

		return entity;
	}

	public Long findTotalNumberTecnica() throws Exception {
		Long entity = null;

		try {
			entity = JPADaoFactory.getInstance().getTecnicaDAO()
			.findTotalNumberTecnica();
		} catch (Exception e) {
			throw new Exception(ExceptionManager.getInstance()
					.exceptionFindingEntity("Tecnica Count"));
		} finally {
			EntityManagerHelper.closeEntityManager();
		}

		return entity;
	}

	/**
	 *
	 * @param varibles
	 *            este arreglo debera tener:
	 *
	 * [0] = String variable = (String) varibles[i]; representa como se llama la
	 * variable en el pojo
	 *
	 * [1] = Boolean booVariable = (Boolean) varibles[i + 1]; representa si el
	 * valor necesita o no ''(comillas simples)usado para campos de tipo string
	 *
	 * [2] = Object value = varibles[i + 2]; representa el valor que se va a
	 * buscar en la BD
	 *
	 * [3] = String comparator = (String) varibles[i + 3]; representa que tipo
	 * de busqueda voy a hacer.., ejemplo: where nombre=william o where nombre<>william,
	 * en este campo iria el tipo de comparador que quiero si es = o <>
	 *
	 * Se itera de 4 en 4..., entonces 4 registros del arreglo representan 1
	 * busqueda en un campo, si se ponen mas pues el continuara buscando en lo
	 * que se le ingresen en los otros 4
	 *
	 *
	 * @param variablesBetween
	 *
	 * la diferencia son estas dos posiciones
	 *
	 * [0] = String variable = (String) varibles[j]; la variable ne la BD que va
	 * a ser buscada en un rango
	 *
	 * [1] = Object value = varibles[j + 1]; valor 1 para buscar en un rango
	 *
	 * [2] = Object value2 = varibles[j + 2]; valor 2 para buscar en un rango
	 * ejempolo: a > 1 and a < 5 --> 1 seria value y 5 seria value2
	 *
	 * [3] = String comparator1 = (String) varibles[j + 3]; comparador 1
	 * ejemplo: a comparator1 1 and a < 5
	 *
	 * [4] = String comparator2 = (String) varibles[j + 4]; comparador 2
	 * ejemplo: a comparador1>1  and a comparador2<5  (el original: a > 1 and a <
	 * 5) *
	 * @param variablesBetweenDates(en
	 *            este caso solo para mysql)
	 *  [0] = String variable = (String) varibles[k]; el nombre de la variable que hace referencia a
	 *            una fecha
	 *
	 * [1] = Object object1 = varibles[k + 2]; fecha 1 a comparar(deben ser
	 * dates)
	 *
	 * [2] = Object object2 = varibles[k + 3]; fecha 2 a comparar(deben ser
	 * dates)
	 *
	 * esto hace un between entre las dos fechas.
	 *
	 * @return lista con los objetos que se necesiten
	 * @throws Exception
	 */
	public List<Tecnica> findByCriteria(Object[] variables,
			Object[] variablesBetween, Object[] variablesBetweenDates)
			throws Exception {
		List<Tecnica> list = new ArrayList<Tecnica>();
		String where = new String();
		String tempWhere = new String();

		if (variables != null) {
			for (int i = 0; i < variables.length; i++) {
				if ((variables[i] != null) && (variables[i + 1] != null) &&
						(variables[i + 2] != null) &&
						(variables[i + 3] != null)) {
					String variable = (String) variables[i];
					Boolean booVariable = (Boolean) variables[i + 1];
					Object value = variables[i + 2];
					String comparator = (String) variables[i + 3];

					if (booVariable.booleanValue()) {
						tempWhere = (tempWhere.length() == 0)
						? ("(model." + variable + " " + comparator + " \'" +
								value + "\' )")
								: (tempWhere + " AND (model." + variable + " " +
										comparator + " \'" + value + "\' )");
					} else {
						tempWhere = (tempWhere.length() == 0)
						? ("(model." + variable + " " + comparator + " " +
								value + " )")
								: (tempWhere + " AND (model." + variable + " " +
										comparator + " " + value + " )");
					}
				}

				i = i + 3;
			}
		}

		if (variablesBetween != null) {
			for (int j = 0; j < variablesBetween.length; j++) {
				if ((variablesBetween[j] != null) &&
						(variablesBetween[j + 1] != null) &&
						(variablesBetween[j + 2] != null) &&
						(variablesBetween[j + 3] != null) &&
						(variablesBetween[j + 4] != null)) {
					String variable = (String) variablesBetween[j];
					Object value = variablesBetween[j + 1];
					Object value2 = variablesBetween[j + 2];
					String comparator1 = (String) variablesBetween[j + 3];
					String comparator2 = (String) variablesBetween[j + 4];
					tempWhere = (tempWhere.length() == 0)
					? ("(" + value + " " + comparator1 + " " + variable +
							" and " + variable + " " + comparator2 + " " + value2 +
					" )")
					: (tempWhere + " AND (" + value + " " + comparator1 +
							" " + variable + " and " + variable + " " +
							comparator2 + " " + value2 + " )");
				}

				j = j + 4;
			}
		}

		if (variablesBetweenDates != null) {
			for (int k = 0; k < variablesBetweenDates.length; k++) {
				if ((variablesBetweenDates[k] != null) &&
						(variablesBetweenDates[k + 1] != null) &&
						(variablesBetweenDates[k + 2] != null)) {
					String variable = (String) variablesBetweenDates[k];
					Object object1 = variablesBetweenDates[k + 1];
					Object object2 = variablesBetweenDates[k + 2];
					String value = null;
					String value2 = null;

					try {
						Date date1 = (Date) object1;
						Date date2 = (Date) object2;
						value = Utilities.formatDateWithoutTimeInAStringForBetweenWhere(date1);
						value2 = Utilities.formatDateWithoutTimeInAStringForBetweenWhere(date2);
					} catch (Exception e) {
						list = null;
						throw e;
					}

					tempWhere = (tempWhere.length() == 0)
					? ("(model." + variable + " between \'" + value +
							"\' and \'" + value2 + "\')")
							: (tempWhere + " AND (model." + variable +
									" between \'" + value + "\' and \'" + value2 + "\')");
				}

				k = k + 2;
			}
		}

		if (tempWhere.length() == 0) {
			where = null;
		} else {
			where = "(" + tempWhere + ")";
		}

		try {
			list = JPADaoFactory.getInstance().getTecnicaDAO()
			.findByCriteria(where);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		} finally {
			EntityManagerHelper.closeEntityManager();
		}

		return list;
	}
}
